package com.csdj.t309springboot.controller;

import com.csdj.t309springboot.common.WebResult;
import com.csdj.t309springboot.common.WebResultMsgCode;
import com.csdj.t309springboot.utils.HttpRestUtil;
import com.csdj.t309springboot.utils.ParameterNameUtils;
import com.csdj.t309springboot.vo.WxAccessRespVo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.Arrays;

/**
 * 微信接口测试号
 */
@RestController
@RequestMapping("/wei/xin")
//@RequestMapping("/wx")
public class WeiXinController extends BaseController{
    @Value("${weiXin.appId}")
    private String wxAppId;
    @Value("${weiXin.appSecret}")
    private String wxAppSecret;

//    @Value("${data.accessKey}")
//    private String accessKey;
//    @Value("${data.accessSecret}")
//    private String accessSecret;

    private Logger log = LoggerFactory.getLogger("wx");

    //页面授权接口
    private final static String OPEN_QRCODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=%s#wechat_redirect";

    //获取access_code接口
    private final static String WX_GET_ACCESS = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";


    private final static String LOGIN_CALLBACK = "http://j4867o7433.zicp.vip/api/wx/login/callback";

    /**
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     */
    @GetMapping("/token")
    public String domainCheck(@RequestParam("signature") String signature,
                              @RequestParam("timestamp") Long timestamp,
                              @RequestParam("nonce") String nonce,
                              @RequestParam("echostr") String echostr) {
        log.info("signature:{} timestamp:{},nonce:{},echostr:{}", signature, timestamp, nonce, echostr);
        return echostr;
    }

    /**
     * 授权回调接口,用state判断用户
     *  前端写个定时任务刷新
     * @param code
     * @param state
     * @param request
     * @return
     */
    @RequestMapping("/login/callback")
    public String loginCallback(String code, String state, HttpServletRequest request) {
        log.info("code:{} state:{}", code, state);
        //获取access_code
        String url = String.format(WX_GET_ACCESS, wxAppId, wxAppSecret, code);
        String resp = HttpRestUtil.get(url, String.class);
        ObjectMapper om = new ObjectMapper();
        WxAccessRespVo accessResp = null;
        try {
            accessResp = om.readValue(resp, WxAccessRespVo.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        if (accessResp != null && StringUtils.hasText(accessResp.getAccess_token())) {
            //获取openid
            System.out.println(accessResp.getOpenid());
        }
        return "success";
    }
    /**
     * 所谓的监听说白了就是在新线程创建一个死循环,循环判断变量值有没有改变
     */
    /**
     * 获取微信登录地址, 然后将地址转换为二维码, 统一资源标识符（Uniform Resource Identifier）
     * 登录是为了验证用户,获取用户标识
     * 返回 accessCode和 openId
     * accessCode:有效期两小时,一般是保存到 redis或数据库里去
     * 用定时任务: 用旧的accessCode换取刷新后的accessCode
     * 获取用户详细信息:用accessToken去查
     *
     * @param state 自定义参数
     * @return https://open.weixin.qq.com/connect/oauth2/authorize?
     *  appid=wx7b192461d2b4963e&redirect_uri=http%3A%2F%2Fj4867o7433.zicp.vip%2Fapi%2Fwx%2Flogin%2Fcallback&
     *  response_type=code&scope=snsapi_base&state=null#wechat_redirect
     * @throws UnsupportedEncodingException 不支持的编码异常
     */
    @GetMapping("/login/qrcode")
    public WebResult getLoginUrl(String state) throws UnsupportedEncodingException {
        String callbackUrl = URLEncoder.encode(LOGIN_CALLBACK, "GBK"); //进行编码
        String qrcode = String.format(OPEN_QRCODE_URL, wxAppId, callbackUrl, state);
        return resp(WebResultMsgCode.SUCCESS, qrcode);
    }
//
//    @Resource
//    private WeiXinUtils weiXinService;
//
//    @GetMapping("/login/get/qrcode")
//    public WebResult get(String code,String state){
//        log.info("code{},state{}",code,state);
//        return new WebResult(WebResultMsgCode.SUCCESS);
//    }
//
//    /**
//     * 微信测试号接入
//     * @param request
//     * @param response
//     */
//    @GetMapping("/wei/xin")
//    public void wx(HttpServletRequest request, HttpServletResponse response) {
//
//        //获取微信服务器发来的参数，并将token、timestamp、nonce三个参数进行字典序排序
//        //将三个参数字符串拼接成一个字符串进行sha1加密
//        //开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
//        String signature = request.getParameter("signature");
//        String timestamp = request.getParameter("timestamp");
//        String nonce = request.getParameter("nonce");
//        String echostr = request.getParameter("echostr");
//        //check方法用来排序以及比较
//        if (weiXinService.check(timestamp, nonce, signature)) {
//            PrintWriter out = null;
//            try {
//                out = response.getWriter();
//                out.print(echostr);
//            } catch (IOException e) {
//                e.printStackTrace();
//            } finally {
//                out.flush();//刷新文件流
//                out.close();//关闭文件流
//            }
//            System.out.println("接入成功");
//        }
//    }


    /**
     * 使用反射获取方法参数名,并对方法参数名进行排序
     * @return
     */
    @GetMapping("/order")
    public String[] order() throws NoSuchMethodException {
        Class<WeiXinController> clazz = WeiXinController.class;
        Method method = clazz.getDeclaredMethod("callback", String.class, String.class, String.class, String.class, String.class, String.class);
        String[] parameterNames = ParameterNameUtils.getMethodParameterNamesByAnnotation(method);
        Arrays.sort(parameterNames);
        return parameterNames;
    }

//    @GetMapping("/testing")
//    public WebResult test1(
//            @RequestParam("username") String username, @RequestParam("email") String email,
//            @RequestParam("nickname") String nickname, @RequestParam("description") String description,
//            @RequestParam("accessKey") String accessKey, @RequestParam("accessSecret") String accessSecret,
//            @RequestParam()String sign) {
//        //accessKey : abcdefg
//        //accessSecret:wienq31fj2ijsf21f2g3
//        TreeMap<Object, Object> map = new TreeMap<>();
//        map.put("username",username);
//        map.put("email",email);
//        map.put("nickname",nickname);
//        map.put("description",description);
//        map.put("accessKey",accessKey);
//
//        //验证参数抽取公共代码封装起来
//        /**
//         * 比较正确的hash值和传过来的参数加密后的hash值是否一致
//         */
////        String[] order = ParameterNameUtils.order();
//        String[] array = {username,email,nickname,description,accessKey,accessSecret};
//        Arrays.sort(array);
//        StringBuffer stringBuffer = new StringBuffer();
//        for (String str:array){
//            stringBuffer.append(str);
//        }
//
//        //正确的加密
////        String data = username + email + nickname + description + accessKey + accessSecret;
//        String data = stringBuffer.toString();
//        System.out.println("data="+data);
//        String dataSha256Encrypt = EncryptUtil.SHA256(data);
//        //传过来的参数加密
//        String newData = username + email + nickname + description+ accessKey+accessSecret;
//
//        String newDataSha256Encrypt = EncryptUtil.SHA256(newData);
//        if(dataSha256Encrypt.equals(newDataSha256Encrypt)){
//            return new WebResult(WebResultMsgCode.SUCCESS);
//        }
//
//
//        return new WebResult(WebResultMsgCode.FAIL);
//    }


}
